package com.nebula.service.Impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.nebula.common.ServerResponse;
import com.nebula.mapper.FilesMapper;
import com.nebula.mapper.UserMapper;
import com.nebula.pojo.Files;
import com.nebula.pojo.User;
import com.nebula.service.IFileUploadService;
import com.nebula.util.FileCharsetDetectorUtil;
import com.nebula.util.FileCharsetUtil;
import com.nebula.util.IDUtil;

@Service("fileUploadService")
public class FileUploadServiceImpl implements IFileUploadService{
	
	@Autowired
	private FilesMapper filesMapper;
	@Autowired
	private UserMapper userMapper;
	
	private Logger logger = LoggerFactory.getLogger(FileUploadServiceImpl.class);
	
	
	public ServerResponse<String> addFiles(MultipartFile fileUpload,HttpServletRequest request,String path,
			String shortUrl,User user){
		int folderId = Integer.parseInt(request.getParameter("folderId"));
		
		long usedSize = userMapper.selectUsedStorageSpaceByUsername(user.getUsername());
		
		if(request.getParameter("chunk") == null){
			if(usedSize + fileUpload.getSize() < user.getUserGroups().getMaxStorageSpace()){
				String fileName = fileUpload.getOriginalFilename();
				
				//扩展名
				String fileExtensionName = fileName.substring(fileName.lastIndexOf(".") + 1);
				
				fileName = fileName.substring(0,fileName.length()-fileExtensionName.length()-1);
				String newFileName = getNewFileName(fileName, user.getUsername(), folderId);
				
				path += "/" + fileExtensionName.toLowerCase();
				
				shortUrl += "/" + fileExtensionName.toLowerCase();
				
				//上传的文件名
				String uploadFileName = UUID.randomUUID().toString() + "." + fileExtensionName;
				File targetFile = new File(path,uploadFileName);
				if(!targetFile.exists()){
					targetFile.setWritable(true);
					targetFile.mkdirs();
				}
				try {
					fileUpload.transferTo(targetFile);
					
					if("txt".equals(fileExtensionName.toLowerCase())){
						File txtCoding = new File(path,uploadFileName);
						String fromCharsetName = FileCharsetDetectorUtil.getFileEncode(txtCoding);
						System.out.println(FileCharsetDetectorUtil.getFileEncode(txtCoding));
						try {
							FileCharsetUtil.convert(txtCoding, fromCharsetName, "UTF-8");
						} catch (Exception e) {
							e.printStackTrace();
							return ServerResponse.createByErrorMessage("上传出错");
						}
					}
					Files files = new Files();
					files.setFileid(IDUtil.getItemId());
					files.setFileRealName(newFileName);
					files.setFileExtension(fileExtensionName);
					files.setFileEncryptionName(uploadFileName);
					files.setInRecycle(1);
					files.setFolderId(folderId);
					files.setUsername(user.getUsername());
					files.setFileSize(fileUpload.getSize());
					files.setFileStoragePath(path + "/" + uploadFileName);
					files.setFileShortUrl(shortUrl + "/" + uploadFileName);
					
					int result = filesMapper.insertSelective(files);
					if(result > 0){
						return ServerResponse.createBySuccessMessage("已上传");
					}else
						return ServerResponse.createByErrorMessage("上传出错");
					
				} catch (IllegalStateException e) {
					e.printStackTrace();
				} catch (IOException e) {
					logger.info("上传文件异常：",e);
				}
			}else{
				return ServerResponse.createByErrorMessage("存储空间不足，请购买存储空间后重试");
			}
		}else{
			String guid = request.getParameter("guid");
			int chunk = Integer.parseInt(request.getParameter("chunk"));
			int chunks = Integer.parseInt(request.getParameter("chunks"));
			//临时目录用来存放所有分片文件
			String tempPath = request.getSession().getServletContext().getRealPath("tempUpload/" + guid);
			File tempFileDir = new File(tempPath);
			if(!tempFileDir.exists()){
				tempFileDir.mkdirs();
			}
			File tempPartFile = new File(tempFileDir,guid + "_" + chunk + ".part");
			try {
				fileUpload.transferTo(tempPartFile);
			} catch (IllegalStateException e) {
				e.printStackTrace();
				try {
					FileUtils.deleteDirectory(tempFileDir);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			} catch (IOException e) {
				logger.info("上传文件异常：",e);
				try {
					FileUtils.deleteDirectory(tempFileDir);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			//判断是否全部上传完成
			boolean uploadDone = true;
			for(int i = 0;i < chunks;i++){
				File partFile = new File(tempFileDir,guid + "_" + i + ".part");
				if(!partFile.exists()){
					uploadDone = false;
				}
			}
			//所有文件上传完成，将分片文件合并到一个文件中
			if(uploadDone){
				String fileName = fileUpload.getOriginalFilename();
				
				//扩展名
				String fileExtensionName = fileName.substring(fileName.lastIndexOf(".") + 1);
				
				fileName = fileName.substring(0,fileName.length()-fileExtensionName.length()-1);
				String newFileName = getNewFileName(fileName, user.getUsername(), folderId);
				
				//上传的文件名
				String uploadFileName = UUID.randomUUID().toString() + "." + fileExtensionName;
				
				path += "/" + fileExtensionName;
				shortUrl += "/" + fileExtensionName;
				
				File finalFilePath = new File(path);
				if(!finalFilePath.exists()){
					finalFilePath.mkdirs();
				}
				File finalFile = new File(finalFilePath,uploadFileName);
				for(int i = 0;i < chunks;i++){
					File partFile = new File(tempFileDir,guid + "_" + i + ".part");
					try {
						FileOutputStream fos = new FileOutputStream(finalFile,true);
						FileInputStream fis = FileUtils.openInputStream(partFile);
						byte buffer[] = new byte[1024];
						int len = 0;
						while((len = fis.read(buffer)) > 0){
							fos.write(buffer,0,len);
						}
						fos.close();
						fis.close();
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if(usedSize + finalFile.length() > user.getUserGroups().getMaxStorageSpace()){
					try {
						FileUtils.forceDelete(finalFile);
						FileUtils.deleteDirectory(tempFileDir);
					} catch (IOException e) {
						e.printStackTrace();
					}
					return ServerResponse.createByErrorMessage("存储空间不足，请购买存储空间后重试");
				}else {
					//将数据存入数据库
					Files files = new Files();
					files.setFileid(IDUtil.getItemId());
					files.setFileRealName(newFileName);
					files.setFileExtension(fileExtensionName);
					files.setFileEncryptionName(uploadFileName);
					files.setInRecycle(1);
					files.setFolderId(folderId);
					files.setUsername(user.getUsername());
					files.setFileSize(finalFile.length());
					files.setFileStoragePath(path + "/" + uploadFileName);
					files.setFileShortUrl(shortUrl + "/" + uploadFileName);
					int result = filesMapper.insertSelective(files);
					if(result > 0){
						//删除临时文件夹
						try {
							FileUtils.deleteDirectory(tempFileDir);
						} catch (IOException e) {
							e.printStackTrace();
						}
						return ServerResponse.createBySuccessMessage("已上传");
					}else{
						try {
							FileUtils.deleteDirectory(tempFileDir);
						} catch (IOException e) {
							e.printStackTrace();
						}
						return ServerResponse.createByErrorMessage("上传出错");
					}
				}
			}else{
				//文件夹创建失败
				if(chunk == chunks - 1){
					try {
						FileUtils.deleteDirectory(tempFileDir);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return null;
	}
	
	public String setNewFileName(Files files){
		return getNewFileName(files.getFileRealName(), files.getUsername(), files.getFolderId());
	}
	
	private String getNewFileName(String oldFileName,String username,int folderId){
		Files file = new Files();
		file.setFileRealName(oldFileName);
		file.setUsername(username);
		file.setFolderId(folderId);
		String newFileName = oldFileName;
		int rowCount = filesMapper.selectFileCount(file);
		int count = 0;
		while(rowCount > 0){
			rowCount = filesMapper.selectFileCount(file);
			if(rowCount > 0){
				count += 1;
				newFileName = oldFileName +  " (" + count + ")";
				file.setFileRealName(newFileName);
			}else {
				rowCount = -1;
			}
		}
		return newFileName;
	}
}
